<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=\, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
     <div>
    EEE
     </div>
     <div>
EEE
     </div>
</body>


</html>
<script>
    //Iterator接口是一种数据遍历的协议

    //  任意一个对象的Symbol.iterator方法
    //  等于该对象的遍历器生成函数 调用该函数会返回该对象的一个遍历器对象
    var myIterable = {};
    myIterable[Symbol.iterator] = function*(){
        yield 1;
        yield 2;
        yield 3;
    }
   console.log( [...myIterable]);//[1,2,3]

   function*gen(){
   }
   var g = gen();
   console.log( g[Symbol.iterator]() === g );
    
   //ES6语法实现斐波那契
   function *fibonacci(){
       let [prev,curr] = [0,1]
       for(;;){
           yield curr;
           [prev,curr] = [curr,prev + curr]
       } 
   }
   for(let  n of fibonacci()){
       if(n > 1000) break;
       console.log(n);
   }

   function* genFuncWithReturn(){
       yield 'a';
       yield 'c';
       yield 'e';
       return 'The result';
   }
   function* logReturned(genObj){
       let result =  yield* genObj;
       console.log(result);
   }
   console.log(...logReturned(genFuncWithReturn()));
   //The result 
   //['a','c','e']

   //使用yield*命令取出嵌套数组的所有成员
   function* iterTree(tree){
       if(Array.isArray(tree)){
           for(let i = 0; i < tree.length ; i++){
               yield *iterTree(tree[i]);
           }
       }else
         yield tree;
   }
   const tree = ['a',['b','c'],['d','e']];
   console.log([...tree]);//['a',Array(2),Array(2)]
   for(let x of iterTree(tree)){
       console.log(x);
   }//a b c d e

   
   //让Generator函数返回一个正常的对象实例 既可以用next方法
   //又可以获得正常的this
   var Obj = {};
   function* G(){
     this.a = 1;
     yield this.b = 2;
     yield this.c = 3;
   }
   //执行的是遍历器对象g 但生成的对象实例是Obj
   //--------------------------------------------//
   var g = G.call(Obj);
   console.log(g.next());
   console.log(g.next())
   console.log(g.next())
   console.log(Obj.a);
   //--------------------------------------------//


   
   function*F(){
       this.a  = 1;
       yield this.b = 2;
       yield this.c = 3;
   }
   var f = F.call(F.prototype)
   //执行的是遍历器对象f 生成的对象实例也是f
   console.log(f.next());
   console.log(f.next());
   console.log(f.next());
//------------------------------------------------//

   //再将F改造成构造函数 就可以对它执行new命令了
   function* ken(){
       this.a = 1;
       yield this.b = 2;
       yield this.c = 3;
   }
   function K(){
       return ken.call(ken.prototype);
   }
   var k = new K();
   console.log(k.next())
   console.log(k.a);
    
   var clock = function* () {
  while (true) {
    yield 'Tick';
    yield 'Tock';
  }
};
    console.log(clock().next());

    //对于类数组对象(存在数值键名和length属性) 部署Iterator接口
    //有一个简便的方法，就是Symbol.iterator方法直接引用数组的Iterator接口
    NodeList.prototype[Symbol.iterator] = [][Symbol.iterator]
    NodeList.prototype[Symbol.iterator] = Array.prototype[Symbol.iterator]
    //注意 普通对象部署数组的Symbol.iterator方法 并无效果
    //只要某个数据结构部署了Iterator接口 就可以对它使用扩展运算符 将其转为数组
    

    for(v of document.getElementsByTagName('div')){
        console.log("1" + v.innerHTML)
    }

    let iterable = {
        0:'a',
        1:'b',
        2:'c',
        length:3,
        [Symbol.iterator]:Array.prototype[Symbol.iterator]
    }
    for(let item of iterable){
        console.log(item)
    }
</script>